// proc.cpp
// Implementation of xp_rot13 extended stored procedure.
// Michael Coles, MCDBA, 7/2005
//

#include <Dblib.h>
#include <params.h>
#include <constants.h>
#include <ROT13_Encode.h>
#include <stdafx.h>
#include <stdexcept>

#ifdef __cplusplus
extern "C" {
#endif

RETCODE __declspec(dllexport) xp_rot13(SRV_PROC *srvproc);

#ifdef __cplusplus
}
#endif

void PrintError (SRV_PROC *srvproc, char *ErrorMsg);

RETCODE __declspec(dllexport) xp_rot13(SRV_PROC *srvproc)
{
	// First we declare a new SQL Parameter object to hold our SQL Parameter.
	params *P1 = new params();
	params *P2 = new params();
	RETCODE rc = XP_NOERROR;
	BYTE* ROT13_Encoded_String = NULL;
	try
	{
		// Now we check the SQL Parameter Count.  We only want a single parameter here.
		if (params::getparamcount(srvproc) != 2) {
			Dblib::printerror(srvproc, USAGE_ROT13);
			rc = XP_ERROR;
		}
		if (rc == XP_NOERROR) {// Now we get the data from SQL Parameter 1
			params::getparam(srvproc, 1, P1);
			params::getparam(srvproc, 2, P2);

			if (P1->isoutput || !P2->isoutput) {
				Dblib::printerror(srvproc, USAGE_ROT13);
				rc = XP_ERROR;
			}

			if (rc == XP_NOERROR) {
				// Here we create the ROT13 Encoded String storage and initialize it to all
				// character zeroes
				ROT13_Encoded_String = new BYTE [P1->length + 1];
				memset(ROT13_Encoded_String, '\0', P1->length + 1);

				// Now we encode the string passed in using ROT13
				ROT13_Encode_String(P1->cdata, ROT13_Encoded_String, P1->length);
			}
		}
	} catch(std::exception ex) {
		Dblib::printerror(srvproc, ERR_ROT13_EXCEPTION);
		rc = XP_ERROR;
	}
	// Next we set the output column data to the encoded ROT13 string
	if (rc == XP_NOERROR)
		srv_paramsetoutput(srvproc, 2, ROT13_Encoded_String, P1->length, FALSE);
	else
		srv_paramsetoutput(srvproc, 2, (BYTE *)"", 0, TRUE);
	srv_senddone(srvproc, SRV_DONE_MORE, (DBUSMALLINT)0, (DBINT)0);

	// A little clean-up.  First delete the ROT13 encoded string
	if (ROT13_Encoded_String != NULL)
		delete [] ROT13_Encoded_String;
	ROT13_Encoded_String = NULL;
	// Now call the destructor for the Parameter object to release data memory
	if (P1 != NULL)
		delete P1;
	P1 = NULL;
	if (P2 != NULL)
		delete P2;
	P2 = NULL;
	return rc;
}